﻿using System;
using System.Data;
using System.Data.Entity;
using System.Data.Objects.SqlClient;
using System.Linq;
using EntityFramework.Extensions;
using Pyramid.Models;
using Pyramid.Security;

namespace Pyramid.Bll
{
	public class PaymentHelper : BllBase
	{
		public static PaymentHelper NewInstance
		{
			get { return new PaymentHelper(); }
		}

		#region query

		/// <summary>
		/// 查询
		/// </summary>
		public IQueryable<PayeeRecord> Query(PaymentQueryModel model, CustomPrincipal user, bool includeAll)
		{
			var records = Db.PayeeRecords
				.Include(x => x.Project)
				.Include(x => x.FinanceAccount)
				.Include(x => x.Verify);

			if (!includeAll)
			{
				records = records.Where(x => x.ApplyUserId == user.UserId);
			}

			if (model.PayerType.HasValue)
			{
				records = records.Where(x => x.PayerType == model.PayerType.Value);
			}
			if (!string.IsNullOrWhiteSpace(model.Keywords))
			{
				var keywords = model.Keywords.Trim();
				records = records.Where(x => x.PayerName.Contains(keywords) || x.Instruction.Contains(keywords));
			}
			if (model.DateTimeFrom.HasValue)
			{
				records = records.Where(x => SqlFunctions.DateDiff("d", model.DateTimeFrom.Value, x.ApplyTime) >= 0);
			}
			if (model.DateTimeTo.HasValue)
			{
				records = records.Where(x => SqlFunctions.DateDiff("d", model.DateTimeTo.Value, x.ApplyTime) <= 0);
			}
			return records;
		}

		/// <summary>
		/// 我的充值记录（顾客）
		/// </summary>
		public IQueryable<PayeeRecord> MyPayment(int customerId)
		{
			var records = Db.PayeeRecords
				.Include(x => x.Project)
				.Include(x => x.FinanceAccount)
				.Include(x => x.Verify);

			records = records.Where(x => x.PayerId == customerId && x.PayerType == (int) PayerTypes.Customer);

			return records;
		}

		public PayeeRecord Single(int id)
		{
			return Db.PayeeRecords.Include(x => x.FinanceAccount).Single(x => x.Id == id);
		}

		#endregion

		#region update or delete

		public void InsertOrUpdate(PayeeRecord record, CustomPrincipal user)
		{
			record.ApplyUserId = user.UserId;
			record.ApplyUserName = user.FullName;
			record.ApplyTime = DateTime.Now;
			record.Year = DateTime.Now.Year;
			record.Month = DateTime.Now.Month;
			record.FinanceAccount = null;

			if (record.Id == 0)
			{
				Db.PayeeRecords.Add(record);
			}
			else
			{
				Db.Entry(record).State = EntityState.Modified;
			}
			Db.SaveChanges();
		}

		public bool Delete(int id)
		{
			var record = Db.PayeeRecords.Single(x => x.Id == id);
			if (record.StatusEnum == PayeeRecordStatus.Verified)
			{
				Alert("收款已确认，不能删除！");
				return false;
			}

			Db.PayeeRecords.Remove(record);
			return true;
		}

		#endregion

		#region statistic for staff

		/// <summary>
		/// 获取员工业绩统计数据
		/// </summary>
		public IQueryable<StaffAchievementViewModel> GetStaffAchievementList(StaffMonthlyQueryModel model)
		{
			var master = Db.StaffAchievementGatherMasters.First(x => x.Year == model.Year && x.Month == model.Month);

			var staves = Db.Staves.Include(x => x.Department).Include(x => x.Position);
			if (!string.IsNullOrWhiteSpace(model.Keywords))
			{
				staves = staves.Where(x => x.Code.Contains(model.Keywords) || x.FullName.Contains(model.Keywords));
			}

			return from s in staves
				join d in Db.StaffAchievementGatherDetails.Where(x => x.MasterId == master.Id) on s.Id equals d.StaffId
				select new StaffAchievementViewModel
				{
					StaffId = s.Id,
					DepartmentName = s.Department.Name,
					FullName = s.FullName,
					Gender = s.Gender,
					Position = s.Position.Name,
					StaffCode = s.Code,
					UserId = s.UserId,
					TotalAmount = d.TotalAmount
				};
		}

		/// <summary>
		/// 指定月份的业绩是否已统计
		/// </summary>
		public StaffAchievementGatherMaster GetMaster(int year, int month)
		{
			return Db.StaffAchievementGatherMasters.FirstOrDefault(x => x.Year == year && x.Month == month);
		}

		/// <summary>
		/// 标记为结算
		/// </summary>
		public bool Settle(int masterId)
		{
			var master = Db.StaffAchievementGatherMasters.FirstOrDefault(x => x.Id == masterId);
			if (master == null)
			{
				Alert("数据已丢失，请联系管理员！");
				return false;
			}

			master.Status = (int) FinanceStatus.Settled;
			Db.SaveChanges();
			return true;
		}

		/// <summary>
		/// 统计指定月份员工的业绩，并存入数据库
		/// </summary>
		public bool GatherStaffAchievement(int year, int month, CustomPrincipal user)
		{
			var master = Db.StaffAchievementGatherMasters.FirstOrDefault(x => x.Year == year && x.Month == month);
			//数据库已存在记录，则删除，以便重新计算
			if (master != null)
			{
				var masterid = master.Id;
				Db.StaffAchievementGatherDetails.Delete(x => x.MasterId == masterid);
				Db.StaffAchievementGatherMasters.Remove(master);
				Db.SaveChanges();
			}

			//验证是否可以进行汇总计算
			if (Db.PayeeRecords.Any(x => x.Year == year && x.Month == month && x.Status == (int) PayeeRecordStatus.Default))
			{
				Alert(string.Format("{0}年{1}月份还存在没有审核的收款，请先审核后再来进行统计！", year, month));
				return false;
			}

			//进行汇总计算
			master = new StaffAchievementGatherMaster {Year = year, Month = month, CreateUserId = user.UserId, CreateTime = DateTime.Now, Status = (int) FinanceStatus.UnSettled};
			Db.StaffAchievementGatherMasters.Add(master);
			Db.SaveChanges();

			var details = from item in (from s in Db.Staves
			                            join pr in Db.PayeeRecords on s.UserId equals pr.ApplyUserId
			                            where pr.Year == year && pr.Month == month
			                            select new {StaffId = s.Id, pr.Amount})
			              group item by item.StaffId
			              into g
			              select new StaffAchievementGatherDetailDto {MasterId = master.Id, StaffId = g.Key, TotalAmount = g.Sum(x => x.Amount)};
			BulkInsert<StaffAchievementGatherDetailDto, StaffAchievementGatherDetail>(details.ToList());
			return true;
		}

		/// <summary>
		/// 员工业绩明细
		/// </summary>
		public IQueryable<PayeeRecord> GetDetails4StaffAchievement(string userId, int year, int month)
		{
			return Db.PayeeRecords
				.Include(x => x.Project)
				.Include(x => x.FinanceAccount)
				.Include(x => x.Verify)
				.Where(x => x.Status == (int) PayeeRecordStatus.Verified && x.ApplyUserId == userId && x.Year == year && x.Month == month);
		}

		/// <summary>
		/// 获取中心的业绩（管理中心 or 会员中心）
		/// </summary>
		public IQueryable<PayeeRecord> GetCenterAchievement(int centerType, int centerId, int year, int month)
		{
			return from u in Db.Accounts.Where(x => x.UserType == centerType)
				join pr in Db.PayeeRecords.Include(x => x.Project)
					.Include(x => x.FinanceAccount)
					.Include(x => x.Verify) on u.UserId equals pr.ApplyUserId
				where u.ExtInfoId == centerId && pr.Status == (int) PayeeRecordStatus.Verified && pr.Year == year && pr.Month == month
				select pr;
		}

		#endregion
	}
}